<?php
/**
 * 用户后台登录类
 * User: Administrator
 * Date: 2019\2\15 0015
 * Time: 15:10
 */

namespace app\Lib\Model\User;
use app\Lib\Exception\BlException;
use app\Lib\InterfaceIn\User\UserHandle;
use app\Lib\InterfaceIn\User\UserLogin as Api;
use app\Lib\Model\DbModel\UserBase;
use app\validate\UserLoginValidate;

class UserLogin implements Api
{
    /**
     * @var
     */
    private $account;
    /**
     * @var
     */
    private $password;
    private $table;
    private $key = 'userLogin';
    private $userToken;
    /** @var UserHandle $user */
    private $user;
    private $cacheTime = 604800;
    private $loginIp;
    /**
     * @param mixed $account
     * @return UserLogin
     */
    public function setAccount($account)
    {
        $this->account = $account;
        return $this;
    }

    /**
     * @param mixed $password
     * @return UserLogin
     */
    public function setPassword($password)
    {
        $this->password = $password;
        return $this;
    }

    /**
     * @param mixed $loginIp
     * @return UserLogin
     */
    public function setLoginIp($loginIp)
    {
        $this->loginIp = $loginIp;
        return $this;
    }

    /**
     * @return array
     * @throws BlException
     */
    public function run()
    {
        //参数验证
        $this->checkData();

        $uid  = UserBase::getUid($this->account);
        $this->user = $user =  (new User($uid));
        //验证账号是否存在
        if($uid<=0 || empty($uid)){
            throw new BlException('账号不存在');
        }
        //验证密码是否正确
        if($this->password != $user->getPassword()){
            throw new BlException('密码错误');
        }
        //判断角色是否可以登录
        if(!$user->getRoleClass()->isAdminLogin()){
            throw new BlException('无法登录');
        }
        //判断账号是否被禁用
        if(!$user->isAllowLogin()){
            throw new BlException('用户已被禁用');
        }
        //账号是否已在登录
        $this->examineIsLogin();
        //存储登录凭证
        $this->getUserToken();
        $userToken = $this->userToken;
        cache($this->getUserLoginKey(),$userToken,$this->cacheTime);
//        throw new BlException(cache($this->getUserLoginKey()));
        cache($userToken,true,$this->cacheTime);
        //修改登录信息
        $this->updateLoginInfo();
        //返回基础信息
        $userInfo = $this->getUserLoginInfo();
        return $userInfo;
    }

    /**
     * 参数验证
     * @throws BlException
     */
    private function checkData(){
        //参数验证
        $data = [
            'account'=>$this->account,
            'password'=>$this->password,
            'loginIp'=>$this->loginIp
        ];
        $validate =  new UserLoginValidate();
        if(!$validate->scene('login')->check($data)){
            throw new BlException($validate->getError());
        }
    }

    private function getUserLoginInfo(){
        $userInfo = [];
        $userInfo['account'] = $this->user->getAccount();
        $userInfo['uid']  = $this->user->getUid();
        $userInfo['nickName']  = $this->user->getNickName();
        $userInfo['roleName']  = $this->user->getRoleClass()->getName();
        $userInfo['roleAlias']  = $this->user->getRoleClass()->getRoleAlias();
        $userInfo['userToken'] = $this->userToken;
        return $userInfo;
    }
    /**
     * 获取用户表
     * @return UserBase
     */
    private function getTable(){
        if(empty($this->table)){
            $this->table = new UserBase();
        }
        return $this->table;
    }

    /**
     * 获取用户的登录key
     * @return string
     */
    private function getUserLoginKey(){
        return  md5($this->key.'_'.$this->user->getUid());
    }

    /**
     * 获取用户的登录token
     * @return string
     */
    private function getUserToken(){
          $this->userToken = $this->getUserLoginKey().'_login_time_'.time();
    }

    /**
     * 验证用户多人同时在线
     * 在线删除旧的登录凭据
     * @return bool
     */
    private function examineIsLogin(){
        $keyCache  =  $this->getUserLoginKey();
        $userToken =  cache($keyCache);
        $userLogin =  cache($userToken);
        if($userToken && $userLogin){
            cache($keyCache,null);
            cache($userLogin,null);
        }
        return true;
    }

    /**
     * 修改登录资料
     * @throws BlException
     */
    private function updateLoginInfo(){
        //修改登录资料
        $model= $this->getTable();
        $data = [
            $model->_last_login_ip=>$this->loginIp,
            $model->_last_login_time=>time(),
        ];
        $result =  $model->where([$model->_id=>$this->user->getUid()])->update($data);
        if(!$result){
            throw new BlException('登录失败');
        }
    }
}